# -*- coding: utf-8 -*-
"""
Created on Tue Feb 13 18:24:10 2018

@author: Allen
"""
import numpy as np
from .metrics import r2_score

class SimpleLinearRegression1( object ):
    def __init__( self ):
        '''
        初始化SimplelinearRegression模型
        '''
        self.a_ = None
        self.b_ = None
        
    def fit( self, x_train, y_train ):
        '''
        根据训练数据集 x_train, y_train 训练简单线性模型
        '''
        numerator = 0.0
        denominator = 0.0
        # 计算x，y的平均值
        x_mean = np.mean( x_train )
        y_mean = np.mean( y_train )
        
        for x_ele, y_ele in zip( x_train, y_train ):
            numerator += ( x_ele - x_mean ) * ( y_ele - y_mean )
            denominator += ( x_ele - x_mean ) ** 2
            
        self.a_ = numerator / denominator
        self.b_ = y_mean - self.a_ * x_mean
        return self
    
    def predict( self, x_predict ):
        '''
        给定待预测数据集x_predict,返回x_predict的结果向量
        '''
        return np.array( [ self._predict( x ) for x in x_predict ] )
    
    def _predict( self, x ):
        '''
        返回单个预测结果
        '''
        return self.a_ * x + self.b_
    
    def score( self, x_test, y_test ):
        '''
        根据测试数据集 x_test, 和真实值 y_test,计算出当前模型的准确度
        '''
        y_predict = self.predict( x_test )
        return r2_score( y_test, y_predict )

'''
使用向量化计算，使用numpy的向量计算，要比使用for循环效率高太多
凡是两个向量的元素相乘再相加，都可以直接写成这两个向量的内积
'''
    
class SimpleLinearRegression2( object ):
    def __init__( self ):
        '''
        初始化SimplelinearRegression模型
        '''
        self.a_ = None
        self.b_ = None
        
    def fit( self, x_train, y_train ):
        '''
        根据训练数据集 x_train, y_train 训练简单线性模型
        '''
        numerator = 0.0
        denominator = 0.0
        # 计算x，y的平均值
        x_mean = np.mean( x_train )
        y_mean = np.mean( y_train )
        
        
        numerator = (x_train - x_mean).dot( y_train - x_mean )
        denominator = (x_train - x_mean).dot(x_train - x_mean)
            
        self.a_ = numerator / denominator
        self.b_ = y_mean - self.a_ * x_mean
        return self
    
    def predict( self, x_predict ):
        '''
        给定待预测数据集x_predict,返回x_predict的结果向量
        '''
        return np.array( [ self._predict( x ) for x in x_predict ] )
    
    def _predict( self, x ):
        '''
        返回单个预测结果
        '''
        return self.a_ * x + self.b_
    def score( self, x_test, y_test ):
        '''
        根据测试数据集 x_test, 和真实值 y_test,计算出当前模型的准确度
        '''
        y_predict = self.predict( x_test )
        return r2_score( y_test, y_predict )